﻿using System;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;
using Axial.DOM;
using System.Web.UI.HtmlControls;

namespace Axial
{
	public static partial class CallHandler
	{
		[CallHandler(typeof(WebUIExtentions))]
		private static string HandleWebUIExtentions(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "Offset")
			{
				if (stack[0] is Control)
					return string.Format("$('#{0}').offset()", (stack[0] as Control).ClientID);
				else
					return string.Format("$({0}).offset()", stack[0]);
			}
			if (method.Name == "AddHandler")
			{
				string control;
				if (stack[0] is Page)
					control = "document";
				else if (stack[0] is Control)
					control = "document.getElementById('" + (stack[0] as Control).ClientID + "')";
				else
					control = stack[0].ToString();
				string eventName = Enum.GetName(typeof(ClientEvent), stack[1]).ToLower();
				string callbackName = (stack[2] as Delegate).Method.Name;
				return string.Format("if (window.attachEvent) {{ {0}.attachEvent('on{1}', {2}) }} else {{ {0}.addEventListener('{1}', {2}, false) }}", control, eventName, callbackName);
			}
			return null;
		}

		[CallHandler(typeof(Unit))]
		private static string HandleUnit(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "get_Value")
				return string.Format("parseInt({0})", called);
			if (method.Name == "get_Type")
				return string.Format("{0}.substring(parseInt({0}).toString().length)", called);
			if (method.Name == "Pixel")
				return "'" + stack[0].ToString() + "px'";
			if (method.Name == "Percentage")
				return "'" + stack[0].ToString() + "%'";
			return null;
		}

		[CallHandler(typeof(Label))]
		private static string HandleLabel(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "set_AssociatedControlID")
				throw new NotImplementedException("setting the associated control id is currently unimplemented because it may require a span tag to change to a label tag");

			string domElement = GetDomElement(called);
			if (method.Name == "set_Text")
				return string.Format("{0}.innerHTML = {1}", domElement, stack[0]);
			if (method.Name == "get_Text")
				return string.Format("{0}.innerHTML", domElement);
			return null;
		}

		[CallHandler(typeof(WebControl))]
		private static string HandleWebControl(MethodInfo method, object called, object[] stack)
		{
			string getControl = GetDomElement(called); 
			if (method.Name == "get_Style")
				return string.Format("{0}.style", getControl);
			if (method.Name == "set_Width")
				return string.Format("{0}.style.display = 'inline-block'; {0}.style.width = {1}", getControl, stack[0]);
			if (method.Name == "get_Width")
				return string.Format("{0}.style.width", getControl);
			if (method.Name == "set_Height")
				return string.Format("{0}.style.display = 'inline-block'; {0}.style.height = {1}", getControl, stack[0]);
			if (method.Name == "get_Height")
				return string.Format("{0}.style.height", getControl);
			if (method.Name == "get_Attributes")
				return string.Format("{0}.attributes", getControl);
			if (method.Name == "set_BackColor")
				return string.Format("{0}.style.backgroundColor = {1}", getControl, stack[0]);
			if (method.Name == "set_BorderColor")
				return string.Format("{0}.style.borderColor = {1}", getControl, stack[0]);
			if (method.Name == "set_BorderStyle")
				return string.Format("{0}.style.borderStyle = {1}", getControl, "'" + Enum.GetName(typeof(BorderStyle), stack[0]).ToLower() + "'");
			if (method.Name == "set_BorderWidth")
				return string.Format("{0}.style.borderWidth = {1}", getControl, stack[0]);
			if (method.Name == "set_CssClass")
				return string.Format("{0}.className = {1}", getControl, stack[0]);
			if (method.Name == "get_Font")
				return string.Format("{0}.style", getControl);
			if (method.Name == "set_ForeColor")
				return string.Format("{0}.style.color = {1}", getControl, stack[0]);
			if (method.Name == "set_TabIndex")
				return string.Format("{0}.setAttribute('tabindex', {1})", getControl, stack[0]);
			if (method.Name == "set_ToolTip")
				return string.Format("{0}.setAttribute('title', {1})", getControl, stack[0]);
			return null;
		}

		[CallHandler(typeof(Control))]
		private static string HandleControl(MethodInfo method, object called, object[] stack)
		{
			string domElement = GetDomElement(called);
			if (method.Name == "set_Visible")
				if ((int)stack[0] == 1)
				{
					// don't overwrite existing display
					return string.Format("if ({0}.style.display == 'none') {0}.style.display = ''", domElement);
				}
				else
					return string.Format("{0}.style.display = 'none'", domElement);
			if (method.Name == "get_Controls")
				return domElement + ".controls";
			if (method.Name == "get_ClientID")
				return domElement + ".id";
			return null;
		}

		[CallHandler(typeof(ControlCollection))]
		private static string HandleControlCollection(MethodInfo method, object called, object[] stack)
		{
			string domElement = GetDomElement(called.ToString().Substring(0, called.ToString().Length - ".controls".Length));
			if (domElement == "document")
				domElement = "'body'";
			if (method.Name == "Add")
				return "$(" + domElement + ").append(" + stack[0] + ")";
			return null;
		}

		[CallHandler(typeof(FontInfo))]
		private static string HandleFontInfo(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "set_Bold")
				return string.Format("{0}.fontWeight = '{1}'", called, (int)stack[0] == 1 ? "bold" : "normal");
			if (method.Name == "set_Italic")
				return string.Format("{0}.fontStyle = '{1}'", called, (int)stack[0] == 1 ? "italic" : "normal");
			if (method.Name == "set_Overline")
				return string.Format("{0}.textDecoration = '{1}'", called, (int)stack[0] == 1 ? "overline" : "overline");
			if (method.Name == "set_Underline")
				return string.Format("{0}.textDecoration = '{1}'", called, (int)stack[0] == 1 ? "underline" : "normal");
			if (method.Name == "set_Strikeout")
				return string.Format("{0}.textDecoration = '{1}'", called, (int)stack[0] == 1 ? "line-through" : "normal");
			if (method.Name == "set_Size")
				return string.Format("{0}.fontSize = '{1}'", called, stack[0]);
			return null;
		}

		[CallHandler(typeof(AttributeCollection))]
		private static string HandleAttributeCollection(MethodInfo method, object called, object[] stack)
		{
			// need to remove .attributes and call setAttribute
			if (method.Name == "set_Item")
			{
				string domElement = called.ToString().Substring(0, called.ToString().Length - ".attributes".Length);
				return string.Format("{0}.setAttribute({1}, {2})", domElement, stack[0], stack[1]);
			}
			return null;
		}

		[CallHandler(typeof(CssStyleCollection))]
		private static string HandleCssStyleCollection(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "get_Item" || method.Name == "set_Item")
			{
				if (stack[0] is int)
					stack[0] = Enum.GetName(typeof(HtmlTextWriterStyle), stack[0]).LowerFirstLetter();
				else
					stack[0] = stack[0].ToString().RemoveOuterCharacters();
				if (method.Name[0] == 'g')
					return called + "." + stack[0];
				return called + "." + stack[0] + " = " + stack[1];
			}
			return null;
		}

		[CallHandler(typeof(TextBox))]
		private static string HandleTextBox(MethodInfo method, object called, object[] stack)
		{
			TextBox textbox = (TextBox)called;
			if (method.Name == "set_Text")
				return string.Format("{0}.value = {1}", GetById(textbox), stack[0]);
			else if (method.Name == "get_Text")
				return string.Format("{0}.value", GetById(textbox));
			return null;
		}

		[CallHandler(typeof(ListControl))]
		private static string HandleListControl(MethodInfo method, object called, object[] stack)
		{
			ListControl listControl = (ListControl)called;
			if (method.Name == "get_Items")
				return string.Format("{0}.options", GetById(listControl));
			else if (method.Name == "get_SelectedValue")
				return string.Format("{0}.options[{0}.selectedIndex].value", GetById(listControl));
			return null;
		}

		[CallHandler(typeof(ListItemCollection))]
		private static string HandleListItemCollection(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "Clear")
				return string.Format("{0}.length = 0", called);
			else if (method.Name == "Add")
				return string.Format("{0}[{0}.length] = {1}", called, stack[0]);
			return null;
		}

		[CallHandler(typeof(DropDownList))]
		private static string HandleDropDownList(MethodInfo method, object called, object[] stack)
		{
			DropDownList dropDownList = (DropDownList)called;
			return null;
		}

		[CallHandler(typeof(ListItem))]
		private static string HandleListItem(MethodInfo method, object called, object[] stack)
		{
			if (method.Name == "set_Text")
				return string.Format("{0}.text = {1}", called, stack[0]);
			else if (method.Name == "set_Value")
				return string.Format("{0}.value = {1}", called, stack[0]);
			return null;
		}

		[CallHandler(typeof(HtmlTableCell))]
		private static string HandleHtmlTableCell(MethodInfo method, object called, object[] stack)
		{
			HtmlTableCell td = (HtmlTableCell)called;
			if (method.Name == "get_Height")
				return GetJQueryById(td) + ".css('height')";
			return null;
		}

		private static string GetDomElement(object called)
		{
			return	called is Page ? "document" : 
					called is Control ? GetById((Control)called) : 
					called.ToString();
		}

		private static string GetById(Control control)
		{
			return string.Format("document.getElementById('{0}')", control.ClientID);
		}

		private static string GetJQueryById(Control control)
		{
			return string.Format("$('#{0}')", control.ClientID);
		}
	}
}
